# 基于API接口获取数据的抽象类
# by lw 2023-11-4

import urllib.parse

from models.projectindex import ProjectIndex


class Downloader():
    """基于API接口获取数据的抽象类
    """

    def __init__(self,
                 site: str = "",
                 site_desc: str = "",
                 region: str = "",
                 url: str = "",
                 http_mothed: str = "GET"):
        """构造函数

        Args:
            site (str, optional): 站点. Defaults to "".
            site_desc (str, optional): 站点描述（网站名称）. Defaults to "".
            region (str, optional): 站内资源的区域范围. Defaults to "".
            url (str, optional): 获取数据列表的API地址. Defaults to "".
            http_mothed (str, optional): http_mothed. Defaults to "GET".
        """
        self.site = site  # 站点
        self.site_desc = site_desc  # 站点描述（网站名称）
        self.region = region  # 站内资源的区域范围
        self.url = url  # 获取数据列表的API地址
        self.params = ""  # API接口参数，这个时API访问的参数
        self.http_mothed = http_mothed  # 访问模式
        # 查询条件参数：
        self.limit_time = {'starttime': "", 'endtime': ""}  # 查询时间条件
        self.keyword = ""  # 查询关键词
        # 分页控制参数
        self.use_pager = True  # 是否使用分页查询
        self.page_size = 10  # 每页记录数
        self.curpage = 0  # 当前查询到的页码
        # 数据统计参数：
        self.total_record = 0  # 数据总记录条数

    # region 基本参数get/set
    def get_site(self):
        """获取站点地址"""
        return self.site

    def set_site(self, site: str):
        """设置站点地址"""
        self.site = site

    def get_site_desc(self):
        """获取站点描述（站点名称）"""
        return self.site_desc

    def set_site_desc(self, site_desc: str):
        """设置站点描述（站点名称）"""
        self.site_desc = site_desc

    def get_url(self):
        """获取url"""
        return self.url

    def set_url(self, url: str):
        """设置url"""
        self.url = url

    def get_params(self):
        """获取访问参数"""
        return self.params

    def set_params(self, params):
        """设置访问参数"""
        self.params = params

    def get_http_mothed(self):
        """获取访问方法"""
        return self.http_mothed

    def set_http_mothed(self, http_mothed: str):
        """获取访问方法"""
        self.http_mothed = http_mothed

    # endregion

    # region 查询的时间条件,在子类中需要改写
    def get_limit_time(self):
        """获取数据时间段限制条件"""
        return self.limit_time

    def set_limit_time(self, starttime: str, endtime: str):
        """设置数据时间段限制条件"""
        self.limit_time['starttime'] = starttime
        self.limit_time['endtime'] = endtime

    # endregion

    # region 查询的关键词,在子类中需要改写
    def get_keyword(self):
        """获取数据查询关键词"""
        return self.keyword

    def set_keyword(self, keyword: str):
        """设置数据查询关键词"""
        self.keyword = keyword

    # endregion

    # region url编码/解码
    def url_quote(self, word: str) -> str:
        """将url编码的字符串转url编码

        Args:
            word (str): 要转码的字符串

        Returns:
            str: 转码后的字符串
        """
        return urllib.parse.quote(word)

    def url_unquote(self, word: str) -> str:
        """将url编码的字符串解码

        Args:
            word (str): 要解码的字符串

        Returns:
            str: 解码后的字符串
        """
        return urllib.parse.unquote(word)

    # endregion

    # region 分页控制参数：
    def is_use_pager(self):
        """获取是否使用分页查询"""
        return self.use_pager

    def set_use_pager(self, use_pager: bool):
        """设置是否使用分页查询"""
        self.use_pager = use_pager

    def get_page_size(self):
        """获取查询每页记录数"""
        return self.page_size

    def set_page_size(self, page_size: int):
        """设置查询每页记录数"""
        self.page_size = page_size

    def get_curpage(self) -> int:
        """获取当前查询页码"""
        return self.curpage

    def set_curpage(self, curpage: int):
        """设置当前查询页码"""
        self.curpage = curpage

    # endregion

    # region 获取、分析数据的方法：
    def try_get_datas(self) -> bool:
        """尝试获取数据，这个是用来获取数据总数的
            注：这个操作方法要在子类中改写
        Returns:
            bool: 是否获取数据成功
        """
        return True

    def get_records(self) -> int:
        """获取数据总记录数

        Returns:
            int: 总记录数
        """
        return self.total_record

    def get_datas(self) -> [ProjectIndex]:
        """获取当前页项目索引数据
            注：这个操作方法要在子类中改写
        Returns:
            []: ProjectIndex数组
        """
        return []

    def is_last_page(self) -> bool:
        """是否是最后一页数据

        Returns:
            bool: True/False
        """
        if self.use_pager:
            return (self.curpage + 1) * self.page_size >= self.total_record
        else:
            return True

    def build_project_index(self, data) -> ProjectIndex:
        """分析一条数据
            注：这个操作方法要在子类中改写
        Args:
            data (_type_): 数据内容（基本都是字符串）

        Returns:
            ProjectIndex: 一条项目索引
        """
        return None

    def to_next_page(self) -> bool:
        """移动到下一页
            注：这个操作方法要在子类中改写，需要设置参数
            
        Returns:
            bool: 是否成功移动到下一页
        """
        if self.is_last_page():
            return False
        self.curpage += 1
        return True

    # endregion

    def build_inner_link_url(self,
                             inner_link: str,
                             check_inner: bool = True) -> str:
        """构造站内连接的url
            注：一般用来构造详情页面的地址，非站内连接返回

        Args:
            inner_link (str):站内连接（相对地址）
            check_inner (bool):是否检查时站内地址

        Returns:
            str: 完整的url地址
        """
        if inner_link.startswith("http://") or inner_link.startswith(
                "https://"):
            if check_inner:
                if inner_link.startswith(self.site): return inner_link
                else: return None
            else: return inner_link
        else:
            if inner_link.startswith("/"):
                return self.site + inner_link
            else:
                return self.site + "/" + inner_link
